.\" Copyright (c) 2009-2020 Julien Nadeau Carriere <vedge@csoft.net>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\"    notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\"    notice, this list of conditions and the following disclaimer in the
.\"    documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
.\" (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd March 22, 2010
.Dt AG_DRIVER 3
.Os
.ds vT Agar API Reference
.ds oS Agar 1.4.0
.Sh NAME
.Nm AG_Driver
.Nd agar low-level driver interface
.Sh SYNOPSIS
.Bd -literal
#include <agar/core.h>
#include <agar/gui.h>
.Ed
.Sh DESCRIPTION
.\" IMAGE(http://libagar.org/widgets/AG_DriverGLX.png, "The Xorg/glx driver")
In Agar, low-level graphics rendering, event processing and window management
is handled by modular "drivers".
A simple class registration interface allows Agar to be "ported" to new
platforms, environments and graphics systems.
In a manner similar to Agar widgets, new Agar "drivers" may be implemented
as part of an application, without need for changing the Agar source code
itself.
.Pp
For the list of drivers included in the Agar distribution, see the
.Xr AG_InitGraphics 3
manual page, under "AVAILABLE DRIVERS".
.Pp
The interface differs based on whether an underlying window system is available.
All drivers are a subclass of
.Ft AG_Driver .
The
.Ft AG_DriverSw
subclass (for "single-window") is used by drivers that do not interface with
an underlying window system.
For example, the "sdlfb" and "sdlgl" drivers use the SDL 1.x API, and are
therefore limited to a single window as far as the native window system is
concerned).
A dumb framebuffer used in an embedded device would also use the
.Ft AG_DriverSw
subclass.
.Pp
The
.Ft AG_DriverMw
subclass (for "multiple-window") is used by drivers that do interface with
an underlying window system.
In a multiple-window environment, each Agar window (e.g., each window created
by
.Xr AG_WindowNew 3 )
is associated with a "native" window.
For example, the "glx" driver uses the GLX API to create an accelerated
rendering context, and also uses the Xlib API to manage windows.
.Pp
The part of the
.Nm
API that deals with low-level event processing is of particular importance
to applications using custom event loops (see
.Xr AG_CustomEventLoop 3
for an example).
It is possible, in a driver-independent fashion, for an application to catch
and process low-level events (see below).
.Sh DRIVER INTERFACE
.nr nS 1
.Ft "AG_Driver *"
.Fn AG_DriverOpen "AG_DriverClass *dc"
.Pp
.Ft "void"
.Fn AG_DriverClose "AG_Driver *d"
.Pp
.Ft "void"
.Fn AG_ListDriverNames "char *buf" "AG_Size buf_len"
.Pp
.Ft int
.Fn AG_UsingGL "AG_Driver *d"
.Pp
.Ft int
.Fn AG_UsingSDL "AG_Driver *d"
.Pp
.Ft int
.Fn AG_GetDisplaySize "AG_Driver *d" "Uint *w" "Uint *h"
.Pp
.nr nS 0
The
.Fn AG_DriverOpen
function creates a new instance of a driver class, as described by
.Fa dc
(see section below).
.Fn AG_DriverClose
destroys a driver instance.
These two functions are seldom used directly, since they are called
internally from either
.Xr AG_InitGraphics 3
or
.Xr AG_WindowNew 3
in the case of multiple-window drivers (which use one driver instance per
window).
.Pp
The
.Fn AG_ListDriverNames
returns a space-separated list of available drivers for the current
platform, into the specified buffer
.Fa buf
of size
.Fa buf_len .
.Pp
The
.Fn AG_UsingGL
and
.Fn AG_UsingSDL
functions return 1 if Agar is using OpenGL or SDL, respectively.
.Fa d 
is a pointer to the driver instance (or if NULL, use the default driver
instance).
.Pp
The
.Fn AG_GetDisplaySize
function obtains the maximum available display area in pixels.
On success, the dimensions are returned into the
.Fa w
and
.Fa h
arguments, and the function returns 0.
.Fa d
is a pointer to the driver instance (or if NULL, use the default driver
instance).
.Sh DRIVER CLASS STRUCTURE
The
.Ft AG_DriverClass
structure inherits from the base
.Xr AG_Object 3
class, and is defined as follows:
.Bd -literal
typedef struct ag_driver_class {
    struct ag_object_class _inherit;

    const char *name;          /* Short name */
    enum ag_driver_type type;  /* Driver type */
    enum ag_driver_wm_type wm; /* Window manager type */
    Uint flags;                /* Driver class options */

    /*
     * Initialization
     */
    int  (*open)(void *d, const char *spec);
    void (*close)(void *d);
    int  (*getDisplaySize)(Uint *w, Uint *h);

    /*
     * Event processing
     */
    void (*beginEventProcessing)(void *d);
    int  (*pendingEvents)(void *d);
    int  (*getNextEvent)(void *d, AG_DriverEvent *dev);
    int  (*processEvent)(void *d, AG_DriverEvent *dev);
    void (*genericEventLoop)(void *d);
    void (*endEventProcessing)(void *d);
    void (*terminate)(void);

    /*
     * Rendering and texture management
     */
    void (*beginRendering)(void *d);
    void (*renderWindow)(AG_Window *w);
    void (*endRendering)(void *d);
    void (*fillRect)(void *d, const AG_Rect *r, const AG_Color *c);
    void (*updateRegion)(void *d, const AG_Rect *r);
    void (*uploadTexture)(void *d, Uint *id,AG_Surface *s, AG_TexCoord *c);
    void (*updateTexture)(void *d, Uint id, AG_Surface *s, AG_TexCoord *c);
    void (*deleteTexture)(void *d, Uint id);
    int (*setRefreshRate)(void *d, int fps);

    /*
     * Clipping and blending control (rendering context)
     */
    void (*pushClipRect)(void *d, const AG_Rect *r);
    void (*popClipRect)(void *d);
    void (*pushBlendingMode)(void *d, AG_AlphaFn s, AG_AlphaFn d);
    void (*popBlendingMode)(void *d);

    /*
     * Hardware cursor interface
     */
    AG_Cursor *(*createCursor)(void *d, Uint w, Uint h,
                               const Uint8 *data, const Uint8 *mask,
                               int xHot, int yHot);

    void (*freeCursor)(void *d, AG_Cursor *curs);
    int  (*setCursor)(void *d, AG_Cursor *curs);
    void (*unsetCursor)(void *d);
    int  (*getCursorVisibility)(void *d);
    void (*setCursorVisibility)(void *d, int flag);

    /*
     * Widget surface operations (rendering context)
     */
    void (*blitSurface)(void *d, AG_Widget *wid, AG_Surface *s,
                        int x, int y);

    void (*blitSurfaceFrom)(void *d, AG_Widget *wid, int s,
                            const AG_Rect *r, int x, int y);
#ifdef HAVE_OPENGL
    void (*blitSurfaceGL)(void *d, AG_Widget *wid, AG_Surface *s,
                          float w, float h);
    void (*blitSurfaceFromGL)(void *d, AG_Widget *wid, int s,
                              float w, float h);
    void (*blitSurfaceFlippedGL)(void *d, AG_Widget *wid, int s,
                                 float w, float h);
#endif
    void (*backupSurfaces)(void *d, AG_Widget *wid);
    void (*restoreSurfaces)(void *d, AG_Widget *wid);
    int  (*renderToSurface)(void *d, AG_Widget *wid, AG_Surface **s);

    /*
     * Rendering operations (rendering context)
     */
    void (*putPixel)(void *d, int x, int y, const AG_Color *c);
    void (*putPixel32)(void *d, int x, int y, Uint32 px);
    void (*putPixelRGB8)(void *d, int x, int y, Uint8 r, Uint8 g, Uint8 b);
#if AG_MODEL == AG_LARGE
    void (*putPixel64)(void *d, int x, int y, Uint64 px);
    void (*putPixelRGB16)(void *d, int x, int y,
                          Uint16 r, Uint16 g, Uint16 b);
#endif
    void (*blendPixel)(void *d, int x, int y, const AG_Color *c,
                       AG_AlphaFn fnSrc, AG_AlphaFn fnDst);

    void (*drawLine)(void *d, int x1, int y1, int x2, int y2,
                     const AG_Color *c);
    void (*drawLineH)(void *d, int x1, int x2, int y, const AG_Color *c);
    void (*drawLineV)(void *d, int x, int y1, int y2, const AG_Color *c);

    void (*drawLineBlended)(void *d, int x1, int y1, int x2, int y2,
                            const AG_Color *c,
                            AG_AlphaFn fnSrc, AG_AlphaFn fnDst);

    void (*drawLineW)(void *d, int x1, int y1, int x2, int y2,
                      const AG_Color *c, float width);
    void (*drawLineW_Sti16)(void *d, int x1, int y1, int x2, int y2,
                            const AG_Color *c, float width, Uint16 mask);

    void (*_Nonnull drawTriangle)(void *_Nonnull, const AG_Pt *_Nonnull,
                                  const AG_Pt *_Nonnull, const AG_Pt *_Nonnull,
                                  const AG_Color *_Nonnull);
    void (*_Nonnull drawPolygon)(void *_Nonnull, const AG_Pt *_Nonnull, Uint,
                                 const AG_Color *_Nonnull);
    void (*_Nonnull drawPolygonSti32)(void *_Nonnull, const AG_Pt *_Nonnull,
                                      Uint, const AG_Color *_Nonnull,
                                      const Uint8 *_Nonnull);

    void (*drawArrow)(void *d, float angle, int x, int y, int h,
                      const AG_Color *c1, const AG_Color *c2);

    void (*drawBoxRounded)(void *d, const AG_Rect *r, int z, int rad,
                           const AG_Color *c1, const AG_Color *c2);
    void (*drawBoxRoundedTop)(void *d, const AG_Rect *r, int z, int rad,
                              const AG_Color *c1, const AG_Color *c2,
                              const AG_Color *c3);

    void (*drawCircle)(void *d, int x, int y, int r, const AG_Color *c);
    void (*drawCircleFilled)(void *d, int x, int y, int r, const AG_Color *c);
    void (*drawRectFilled)(void *d, const AG_Rect *r, const AG_Color *c);
    void (*drawRectBlended)(void *d, const AG_Rect *r, const AG_Color *c,
                            AG_AlphaFn fnSrc, AG_AlphaFn fnDst);
    void (*drawRectDithered)(void *d, const AG_Rect *r, const AG_Color *c);

    /* Typography */
    void (*updateGlyph)(void *d, AG_Glyph *gl);
    void (*drawGlyph)(void *d, const AG_Glyph *gl, int x, int y);

    /* Display list management (GL driver specific) */
    void (*deleteList)(void *d, Uint listID);

    /* Clipboard access */
    char *(*getClipboardText)(void *);
    int   (*setClipboardText)(void *, const char *);
} AG_DriverClass;
.Ed
.Pp
The
.Va type
field should be set to
.Dv AG_FRAMEBUFFER
for dumb-framebuffer drawing, or
.Dv AG_VECTOR
for vector-based drawing such as OpenGL.
.Pp
The
.Va wm
field may be set to
.Dv AG_WM_SINGLE
for single-window drivers, or
.Dv AG_WM_MULTIPLE
for multiple-window drivers.
.Pp
Acceptable values for the
.Va flags
field include:
.Bl -tag -compact -width "AG_DRIVER_TEXTURES "
.It AG_DRIVER_OPENGL
OpenGL calls are supported.
.It AG_DRIVER_SDL
SDL 1.x calls are supported.
.It AG_DRIVER_TEXTURES
Texture management operations are supported.
.El
.Pp
The
.Fn open
method is invoked to initialize a new driver instance.
.Fn open
is expected to initialize the
.Va mouse
and
.Va kbd
fields of
.Nm
(see
.Xr AG_MouseNew 3 ,
.Xr AG_KeyboardNew 3 ) .
Return 0 on success and -1 on failure.
.Pp
The
.Fn close
method is invoked to destroy a driver instance.
It is expected to destroy the
.Va mouse
and
.Va kbd
fields of
.Nm .
.Pp
The
.Fn getDisplaySize
operation should return the total display size available, in pixels, into
.Fa w
and
.Fa h .
For single-window drivers, this is the size of the display available to
Agar.
For multiple-window drivers, this is the total size of the desktop (if
multiple workspaces are supported, it should be limited to the size of
a single workspace in pixels).
This operation should return 0 on success and -1 on failure.
.Pp
The
.Fn beginEventProcessing
callback is invoked before event processing begins.
Most drivers will not need to do anything here.
.Pp
.Fn pendingEvents
returns a non-zero value if there are events waiting to be processed (see
.Fn AG_PendingEvents ) .
.Pp
.Fn getNextEvent
retrieves and remove the next event from the queue (see
.Fn AG_GetNextEvent ) .
.Pp
.Fn processEvent
processes the event described by
.Fa dev
(see
.Fn AG_ProcessEvent ) .
.Pp
The
.Fn genericEventLoop
method is obsolete as of Agar-1.5 (see
.Xr AG_EventLoop 3 ) .
.Pp
The
.Fn endEventProcessing
callback is invoked after event processing is done.
For most drivers, there is nothing to do here.
.Pp
The
.Fn terminate
operation is obsolete as of Agar-1.5 (see
.Xr AG_Terminate 3 ) .
.Pp
The
.Fn beginRendering
and
.Fn endRendering
operations are invoked by
.Xr AG_BeginRendering 3
and
.Xr AG_EndRendering 3
to prepare for rendering of GUI elements.
.Pp
The
.Fn renderWindow
operation renders an Agar window.
Usually, it will simply invoke
.Xr AG_WidgetDraw 3
on
.Fa win .
Framebuffer drivers may also want to update video regions from here.
.Pp
The
.Fn fillRect
operation is expected to fill a rectangle
.Fa r
with color
.Fa c .
.Pp
The
.Fn updateRegion
operation, usually specific to framebuffer drivers, is expected to update
a region of video memory represented by
.Fa r .
.Pp
.Fn uploadTexture ,
.Fn updateTexture
and
.Fn deleteTexture
are specific to drivers with texture management facilities.
.Fn uploadTexture
creates a texture from an
.Xr AG_Surface 3 ,
returning the computed texture coordinates.
.Fn updateTexture
is expected to update an existing texture from a recently modified surface.
.Fn deleteTexture
arranges for the specified texture to be deleted as soon as possible.
.Pp
The
.Fn setRefreshRate
operation is invoked by
.Xr AG_SetRefreshRate 3 ,
to configure a fixed refresh rate, as a driver-specific hint that can
be ignored.
.Pp
.Fn pushClipRect
should create a clipping rectangle over
.Fa r .
If a clipping rectangle is already in effect, it should be saved on a stack.
.Fn popClipRect
pops the last clipping rectangle off the stack.
.Pp
.Fn pushBlendingMode
should configure an alpha blending mode (see
.Xr AG_AlphaFn 3 ) .
If a blending mode is already set, it should be saved on a stack.
.Fn popBlendingMode
pops the last blending mode off the stack.
.Pp
The following operations are optional and provide Agar with access over
hardware cursors.
See
.Xr AG_Cursor 3
for details on the Agar cursor control interface.
.Pp
The
.Fn createCursor
operation creates a hardware cursor from the bitmap data
.Fa data
and transparency mask
.Fa mask .
The hotspot coordinates are given in
.Fa xHot ,
.Fa yHot .
If a hardware cursor cannot be allocated, the call should return NULL.
.Fn freeCursor
destroys any hardware cursor corresponding to the given
.Ft AG_Cursor
structure.
.Pp
The
.Fn setCursor
operation changes the current cursor to the specified cursor, returning 0
on success or -1 on failure.
.Fn unsetCursor
reverts to the default cursor.
.Pp
The
.Fn getCursorVisibility
and
.Fn setCursorVisibility
routines retrieve and set the cursor visibility flag.
.Pp
The following operations form the backend of the
.Xr AG_Widget 3
surface operations such as
.Xr AG_WidgetBlitFrom 3 .
They all accept a
.Ft AG_Widget
argument, and coordinate arguments are always with respect to the widget's
local coordinate system.
.Pp
.Fn blitSurface
implements
.Xr AG_WidgetBlit 3 ,
which performs an unaccelerated (software) blit from any
.Xr AG_Surface 3 ,
to target coordinates
.Fa x ,
.Fa y .
Note: Efficient code should use
.Fn blitSurfaceFrom
instead.
.Pp
.Fn blitSurfaceFrom
implements
.Xr AG_WidgetBlitFrom 3 ,
which uses a widget-mapped surface as source.
If a texture unit is available then the previously uploaded hardware texture
is used as source.
If texture hardware is not available, a software blit is done.
.Pp
The
.Fn blitSurfaceGL
and
.Fn blitSurfaceFromGL
variants are specific to OpenGL drivers.
Instead of accepting an explicit source or destination rectangle parameter,
they rely on the current transformation matrix being set accordingly.
.Fn blitSurfaceFlippedGL
reverses the order of the rows in the image.
.Pp
The
.Fn backupSurfaces
operation should create a software backup of all surfaces registered under
the given widget.
.Fn restoreSurfaces
restores a widget's surfaces from backup.
These operations are needed with OpenGL on some platforms, where a window
resize may result in a loss of OpenGL context data.
.Pp
The
.Fn renderToSurface
operation renders a widget to a newly allocated
.Xr AG_Surface 3 ,
returned into the
.Fa su
argument.
The function should return 0 on success or -1 on failure.
.Pp
.Fn putPixel ,
.Fn putPixel32 ,
.Fn putPixel64 ,
.Fn putPixelRGB8
and
.Fn putPixelRGB16
write a packed pixel of specified color at coordinates
.Fa x ,
.Fa y .
If the display surface uses 8-bit precision components,
.Fn putPixel64
and
.Fn putPixelRGB16
should compress component ranges to the best 8-bit approximation.
.Pp
.Fn blendPixel
blends the pixel at
.Fa x ,
.Fa y
against the specified
.Ft AG_Color
using the source and destination blending factors
.Fa fnSrc
and
.Fa fnDst .
.Pp
.Fn drawLine
renders a line of color
.Fa C
from endpoint
.Fa x1 ,
.Fa y1
to endpoint
.Fa x2 ,
.Fa y2 .
The
.Fn drawLineH
operation renders a horizontal line, and
.Fn drawLineV
renders a vertical line.
.Fn drawLineBlended
renders a line with transparency (see
.Xr AG_AlphaFn 3 ) .
.Pp
.Fn drawArrow
renders an arrow of length
.Fa h
at coordinates
.Fa x ,
.Fa y
and clockwise rotation
.Fa angle
(0=up, 90=right, 180=down, 270=left).
.Pp
.Fn drawBoxRounded
renders a 3D-style box of depth
.Fa z ,
with corners rounded to radius
.Fa rad .
The
.Fn drawBoxRoundedTop
variant only rounds the two top corners.
.Pp
The
.Fn drawCircle
operation renders a circle of radius
.Fa r ,
centered around
.Fa x ,
.Fa y .
The
.Fn drawCircle2
variant adds a 3D-style effect.
.Pp
The
.Fn drawRectFilled
operation fills the target rectangle
.Fa r
with the given color
.Fn drawRectBlended
renders a filled rectangle with transparency (see
.Xr AG_AlphaFn 3 ) .
.Fn drawRectDithered
renders a filled rectangle with ditering effect (commonly used to illustrate
"disabled" GUI controls).
.Pp
The
.Fn updateGlyph
operation ensures that the specified font glyph (see
.Xr AG_Text 3 )
is ready to be rendered.
OpenGL drivers, for example, can use this operation to upload a rendered
version of the glyph to the texture hardware.
The
.Fn drawGlyph
operation renders a given font glyph at target coordinates
.Fa x ,
.Fa y .
The target point will correspond to the top left corner of the rendered glyph.
.Pp
The
.Fn deleteList
operation arranges for the specified display list to be deleted as soon as
possible (typically in the
.Fn endRendering
routine).
.Pp
The optional
.Fn getClipboardText
operation returns a newly-allocated string with the clipboard contents (in UTF-8).
The returned string is freeable by the caller.
.Pp
The optional
.Fn setClipboardText
operation sets the clipboard contents to a copy of the given UTF-8 string
and returns 0 on success or -1 on failure.
.Sh EVENT PROCESSING
.nr nS 1
.Ft int
.Fn AG_PendingEvents "AG_Driver *d"
.Pp
.Ft int
.Fn AG_GetNextEvent "AG_Driver *d" "AG_DriverEvent *dev"
.Pp
.Ft int
.Fn AG_ProcessEvent "AG_Driver *d" "AG_DriverEvent *dev"
.Bd -literal
/* Requires Agar compiled --with-sdl */
.Ed
.Ft int
.Fn AG_SDL_TranslateEvent "AG_Driver *d" "const SDL_Event *ev" "AG_DriverEvent *dev"
.Pp
.Ft void
.Fn AG_WindowProcessQueued "void"
.Pp
.nr nS 0
Low-level driver events are represented by the
.Ft AG_DriverEvent
structure, which provides the public members
.Va type
and
.Va win .
The
.Va win
member is a pointer to the corresponding
.Xr AG_Window 3
(for single-window drivers,
.Va win
is always NULL).
The
.Va type
field is an enum that can take on the values:
.Pp
.Bl -tag -compact -width "AG_DRIVER_MOUSE_BUTTON_DOWN "
.It AG_DRIVER_MOUSE_MOTION
Mouse cursor has moved to coordinates
.Va data.motion.{x,y} .
.It AG_DRIVER_MOUSE_BUTTON_DOWN
.It AG_DRIVER_MOUSE_BUTTON_UP
Mouse button has been pressed or released at coordinates
.Va data.button.{x,y} .
The button index is passed as
.Va data.button.which .
.It AG_DRIVER_MOUSE_ENTER
.It AG_DRIVER_MOUSE_LEAVE
The mouse cursor has entered or left the window area.
These events are specific to multiple-window drivers.
.It AG_DRIVER_FOCUS_IN
.It AG_DRIVER_FOCUS_OUT
Application focus has been gained or lost.
These events are specific to multiple-window drivers.
.It AG_DRIVER_KEY_DOWN
.It AG_DRIVER_KEY_UP
A key has been pressed or released.
The keysym (see
.Xr AG_KeySym 3 )
is passed as
.Va data.key.ks .
A 32-bit Unicode (UCS-4) representation of the corresponding character, if
any, is passed as
.Va data.key.ucs .
.It AG_DRIVER_EXPOSE
The underlying graphics system is requesting a refresh of the video display.
.It AG_DRIVER_VIDEORESIZE
The application window has been resized to
.Va data.videoresize.{w,h} .
Some drivers may also raise this event when the window is moved.
.It AG_DRIVER_CLOSE
The user has requested that a window be closed.
For multiple-window drivers, the default behavior is to post a
.Sq window-close
event to the corresponding Agar window.
For single-window drivers, the application is usually terminated as a result.
.El
.Pp
The
.Fn AG_PendingEvents
function returns 1 if there are events waiting to be processed, or 0 if the
event queue is empty.
.Pp
.Fn AG_GetNextEvent
retrieves and removes the next event on the queue, initializing the structure
pointed by
.Fa dev
with its contents.
.Fn AG_GetNextEvent
returns 1 if the event has been successfully retrieved into
.Fa dev .
The function returns 0 if the event was dequeued (and no further processing
is required), or -1 if an error has occurred.
.Pp
.Fn AG_ProcessEvent
processes the event pointed to by
.Fa dev
in the default manner.
The call returns 1 if the event was successfully, 0 if Agar has ignored the event entirely,
or -1 if an error has occurred.
.Pp
The
.Fn AG_SDL_TranslateEvent
function translates a
.Xr SDL_Event 3
structure to an Agar
.Fn AG_DriverEvent .
This function is only available if Agar was compiled with SDL support.
Agar supports more than one driver instance per application.
The
.Fa d
argument of
.Fn AG_PendingEvents ,
.Fn AG_GetNextEvent ,
.Fn AG_ProcessEvent
and
.Fn AG_SDL_TranslateEvent
can be set to NULL, in which case the default driver instance will be used.
.Sh EXAMPLES
.\" MANLINK(AG_CustomEventLoop)
The following code fragment implements a basic event loop.
It retrieves pending events, examines them, and forwards them to Agar
for processing:
.Bd -literal -offset indent
AG_DriverEvent ev;

while (AG_PendingEvents(NULL) > 0) {
	if (AG_GetNextEvent(NULL, &ev)) {
		switch (ev.type) {
		case AG_DRIVER_MOUSE_BUTTON_DOWN:
			printf("Click at %d,%d\\n",
			    dev.data.button.x,
			    dev.data.button.y);
			break;
		case AG_DRIVER_KEY_DOWN:
			printf("Key pressed: %d\\n",
			    (int)dev.data.key.ks);
			break;
		default:
			break;
		}
		if (AG_ProcessEvent(NULL, &ev) == -1)
			break;
	}
}
.Ed
.Sh SEE ALSO
.Xr AG_GL 3 ,
.Xr AG_InitGraphics 3 ,
.Xr AG_Intro 3 ,
.Xr AG_Widget 3 ,
.Xr AG_Window 3
.Sh HISTORY
The
.Nm
interface first appeared in Agar 1.4.0.
Agar 1.6.0 added the driver operations
.Fn putPixel64 ,
.Fn putPixelRGB16 ,
.Fn drawTriangle ,
.Fn drawPolygon ,
.Fn drawPolygonSti32 ,
.Fn drawLineW ,
.Fn drawLineW_Sti16 ,
.Fn getClipboardText
and
.Fn setClipboardText .
